<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>迭代</title>
</head>

<body>
    <img src="" width="10" style="width: 20px;" alt="">
    <pre>
        <h4>迭代器</h4>
        可迭代 就是实现了 iterable接口的对象 具有Symbol.iterator 属性 这个属性值是个方法，调用它就能生成迭代器
        包含元素的个数有限，且具有无歧义的遍历顺序
        接收可迭代对象的原生语言特性 包括
         for-of 循环
         数组解构
         扩展操作符
         Array.from()
         创建集合
         创建映射
         Promise.all()接收由期约组成的可迭代对象
         Promise.race()接收由期约组成的可迭代对象
         yield*操作符，在生成器中使用

        迭代器协议
        迭代器是一个次行的消费对象，通过不断的调用next()来获取当前位置信息
        调用next()会得到一个对象{value， done} value为undefined done为true时说明已经消费完了
        
        可选的 return()方法用于指定在迭代器提前关闭时执行的逻辑。执行迭代的结构在想让迭代器知
道它不想遍历到可迭代对象耗尽时，就可以“关闭”迭代器。如关键字break return  continue
  

        <h4>生成器</h4>
        通过 在 function 关键字后面加* 就能定义一个生成器，调用生成器函数会得到一个 <b>生成器对象</b>
        生成器对象是可迭代的，  也可以调用next()进行消费，生成器的迭代器默认指向自身 
        生成器函数内部可使用 yield关键字 中断和开始执行
        生成器实例之间是互不影响的
        所有的生成器对象都有return方法 一旦关闭就无法恢复
    </pre>
</body>

<script>
    let str1 = `sfhwoen`;
    let iteration = str1[Symbol.iterator].bind(str1)
    // 调用这个方法时要让this指向可迭代对象 结果就是一个迭代器
    // console.log(iteration.call(iteration));
    let iter = iteration(), node;
    while (!node?.done) {
        node = iter.next()
        console.log(node)
        /*{
    "value": "s",
    "done": false

    done为true 表示已经到了最后一个
}*/
    }

    class Counter {
        constructor(limit) {
            this.couter = 1;
            this.limit = limit;
        }



        [Symbol.iterator]() {
            let limit = this.limit, count = 1;
            return {
                next() {
                    let res = count < this.limit ? { value: coute++, done: false } : { value: undefined, done: true }
                    return res;
                },
                return() {
                    return { done: true }
                }
            }
        }
    }

    function* generation() {
        yield 1
        yield 2
    }
    /*生成器默认是自引用的*/
    let iter2 = generation()
    console.log(iter2[Symbol.iterator]() === iter2)
    console.log(iter.next())

    function* nTimes(n) {
        let i = 0;
        while (n--) {
            yield i++
        }
    }

    function* range(start, end) {
        let i = 0;
        while (start < end) {
            yield i++;
        }
    }
    /* 生成器也可以作为对象属性 和静态类属性*/

    let genar12 = {
        * count(n) {
            yield n
            while (n--) {

                yield n
            }
        }
    }
    let arr3 = genar12.count(10)
    for (let n of arr3) {
        console.log(n);
    }

    let ps = new Array(4).fill().map(i => new Promise(()=>{}))

    function* fna(arr) {
        for (let  num of arr) {
            yield num
        }
    }

    function co(p = new Promise()) {
        let fn = fna();
        next()
        function next(data) {
            let result = fn.next()
            if (!result.done) {
                result.value.then((info) => {
                    next(info)
                })
            }
        }
    }

    /* 可以用*增强yield 关键字，我的理解就是类似展开数组*/
    function gerat123() {
        yield * [3, 45, 6, 67]
        yield * [9, 12, 3, 4]
    }

    /*用于递归 */
    class Node {
        constructor(id) {
            this.id = id;
            this.neighbors = new Set();
        }
        connect(node) {
            if (node !== this) {
                this.neighbors.add(node);
                node.neighbors.add(this);
            }
        }
    }
    class RandomGraph {
        constructor(size) {
            this.nodes = new Set();
            // 创建节点
            for (let i = 0; i < size; ++i) {
                this.nodes.add(new Node(i));
            }
            // 随机连接节点
            const threshold = 1 / size;
            for (const x of this.nodes) {
                for (const y of this.nodes) {
                    if (Math.random() < threshold) {
                        x.connect(y);
                    }
                }
            }
        }
        // 这个方法仅用于调试
        print() {
            for (const node of this.nodes) {
                const ids = [...node.neighbors]
                    .map((n) => n.id)
                    .join(',');
                console.log(`${node.id}: ${ids}`);
            }
        }
        isConnected() {
            const visitedNodes = new Set();
            function* traverse(nodes) {
                for (const node of nodes) {
                    if (!visitedNodes.has(node)) {
                        yield node;
                        yield* traverse(node.neighbors);
                    }
                }
            }
            // 取得集合中的第一个节点
            const firstNode = this.nodes[Symbol.iterator]().next().value;
            // 使用递归生成器迭代每个节点
            for (const node of traverse([firstNode])) {
                visitedNodes.add(node);
            }
            return visitedNodes.size === this.nodes.size;
        }

    }

    let iteratorObj = {
        * [Symbol.iterator](){
         yield 1 
         yield 2 
         yield 3 
         }
    }

</script>

</html>